$trujs defined in the library<span trujs-init="$trujs.a = 20; $trujs.b = 'Wow!'"></span> ->
TruJS variables, a and b, will be created in $trujs as properties with the initial values.
$trujs.a -> 20 and $trujs['b'] -> 'Wow!'.
$trujs.', i.e., properties in $trujs.<input type='text' trujs-model='x' value='10'> -> The input value will be modelled by $trujs.x with the initial value 10.<span trujs-bind='a, b, c'> let d = 10; $trujs.a++; d + ", " + $trujs.b + ", " + $trujs.c </span> -> The TruJS expression, i.e., the content of <span>...</span>, will be initially evaluated and re-evaluated whenever there is any change in any one of a, b, and c.trujs-bind='' -> The TruJS expression will be evaluated only once in the beginning.<span trujs-bind=...> let d = 10; $trujs.a++; d + " " + $trujs.b + " " + $trujs.c + " " + $trujs.x; </span>$trujs as properties.<input trujs-init='x'> -> $trujs.x (or $trujs['x']) in JavaScript -> multiple <span trujs-bind='x...'>
<script src="https://cs.tru.ca/~mlee/comp4620/Software/TruJS.mo.js"></script> <span trujs-init='$trujs.b = 20'></span> <span trujs-init=''>$trujs.c = 30</span> Case 1: <input type='text' trujs-model='x' value=''><br> Case 2: <input type='text' trujs-model='y' value='TruJS'><br> Case 3: <input type='text' trujs-model='z' value='Fun'><br> <br> <div> Wow!<br><br> Case 1: <span trujs-bind='x'>$trujs.x</span><br> <!-- '$trujs.x' to be evaluated whenever trujs.x is updated. --> Case 2.1: <span trujs-bind='y'></span><br> <!-- no expression --> Case 2.2: <span trujs-bind=''>$trujs.y</span><br> <!-- '$trujs.y' to evaluated only once because trujs-bind does not include y. --> Case 2.3: <span >$trujs.y</span><br> <!-- no evaluation because trujs-bind is not defined. --> Cases 1 and 3: <span trujs-bind='x, z'>let a = 10; $trujs.b++; a + ", " + $trujs.b + ", " + $trujs.c + ", " + $trujs.x + ", " + $trujs.z.toUpperCase()</span><br> </div> <!-- The next code is used just for testing. Without it, Trial 1 would not work, because the TruJS library scans all the elements only with the 'onload' event on 'window'. --> <script> $trujs_init(); </script>
$trujs_init(), if there is a syntax error, then JavaScript stops.)
$trujs = {}; // models and values; each model --> value; E.g., let model = 'a'; $trujs[model] = 20;
$trujs._expressions = {}; // models and expressions; each model --> linear array of objects;
// each object, {output:..., expr:...}, includes
// output: span element object, and
// expr: JS expression that is the content of the span element
// E.g., $trujs._expressions[model].push({output:..., expr:...});
// E.g., $trujs['a'] -> 20;
// $trujs._expressions['a'] -> [{output:spanobj, expr:'$trujs.a += 20;'}, ...]
trujs-model='m'.$trujs['m'] with the new value.i = 0 to $trujs._expressions['m'].length - 1, evaluate $trujs._expressions['m'][i].expr, and$trujs._expressions['m'][i].output.innerHTML.
$trujs
$trujs._expressions
$trujs
$trujs._expressions
$trujs._expressions
$trujs._expressions
$trujs$trujs._expressions$trujs, in the TruJS library.<span>s with trujs-init and save them in $trujs.
Let's evaluate the expression in <span> that uses the two TruJS variables.
How? eval()
<input>s with trujs-model and save them in $trujs.trujs-bind.
$trujs, and they will be evaluated by using 'eval()'.a and b are collected in $trujs in the previous Trial.
m;$trujs[m];$trujs._expressions[m],
evaluate expression and update the output;
$trujs._expressions.trujs-model.
Test the data-view binding by entering something in the <input>s.
.querySelectorAll() and use?
document.querySelectorAll() with attribute selectors$trujs in trujs-init and in expressions.
How to remove $trujs from trujs-init and expressions in bind <spans>?
For examples, <span trujs-init='d = 23; e=45'></span> and
<span trujs-bind = 'd'>a + b + c + d</span>.
function $trujs_update()
{
// Step1: Select the <span>s that include trujs-init, and initialize TruJS models
let init_spans = document.querySelectorAll("span[trujs-init]");
for (let i = 0; i < init_spans.length; i++) {
let init_models = init_spans[i].getAttribute("trujs-init").trim().split(/; */);
for (let j = 0; j < init_models.length; j++) {
if (!init_models[j].startsWith("_expressions")) {
let str = "$trujs." + init_models[j].trim(); // Ahha! "$trujs." is attached.
eval(str);
}
}
}
for (let p in $trujs) {
if (p != "_expressions") // i.e., a model
$trujs._expressions[p] = [];
}
}
function $trujs_update()
{
// Step 4. Initial evaluation
// The same idea in Step 5 can be used.
// Step 5. Select the <input>s that include trujs-model, and register 'keyup' event listeners
// In the event listener, update the model, evaluate the related expressions, and update the related s.
let model_inputs = document.querySelectorAll("input[trujs-model]");
for (let i = 0; i < model_inputs.length; i++) {
model_inputs[i].addEventListener('keyup', function() {
let model = this.getAttribute('trujs-model').trim();
$trujs[model] = ????
for (let j = 0; j < $trujs._expressions[model].length; j++) {
let output_span = ????
let expr = "{";
for (let p in $trujs)
if (p != "_expressions")
expr += `let ${p} = '${$trujs[p]}';`; // Ahha! New local variables with all the models in $trujs
expr += $trujs._expressions[model][j].expr; // Ahha! The variables here will use those declared above.
expr += "}";
???? // upate the output with the evaluation result
}
});
}
}